package com.hcy.app.screen.nfc

import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.nfc.tech.Ndef
import android.util.Log
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import java.nio.charset.StandardCharsets

class NfcHandler: NfcAdapter.ReaderCallback {
    // 暴露 NFC 结果的 StateFlow
    private val _nfcResult = MutableStateFlow<String>("")
    val nfcResult: StateFlow<String> = _nfcResult

    private val _currentTag = MutableStateFlow<Tag?>(null)
    val currentTag: StateFlow<Tag> = _currentTag.asStateFlow() as StateFlow<Tag>

    override fun onTagDiscovered(tag: Tag?) {
        try {
            _currentTag.value = tag
            val data= NFCUtils.readNfcTagData(tag)
            _nfcResult.value = data
            Log.d("miao", "读取成功: $data")
        } catch (e: Exception) {
            _nfcResult.value = "NFC 读取失败:"+e.message
            Log.e("miao", "错误: ${e.message}")
        }
    }
}


object NFCUtils {

    /**
     * 读取 NFC 标签数据
     * @param tag 标签
     * @return 内容（空字符串表示失败）
     */
    fun readNfcTagData(tag: Tag?): String {
        if (tag == null) return ""

        val ndef = Ndef.get(tag)
        val str= ndef?.run {
            try {
                connect()
                val message = ndefMessage
                message?.let { parseNdefMessage(it) } ?: ""
            } catch (e: Exception) {
                e.printStackTrace()
                ""
            } finally {
                try {
                    close()
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
        }?: ""

        return str
    }

    /**
     * 解析 NDEF 消息.
     * NDEF（NFC Data Exchange Format，NFC 数据交换格式）是用于在 NFC（近场通信）设备或标签之间标准化数据存储和传输的通用格式。
     */
    private fun parseNdefMessage(message: NdefMessage): String {
        return buildString {
            message.records.forEach { record ->
                when {
                    // TNF_WELL_KNOWN,标准记录类型，包括：Text 、URI 、Smart Poster 等等
                    record.tnf == NdefRecord.TNF_WELL_KNOWN -> {
                        when {
                            // 一般文本
                            record.type.contentEquals(NdefRecord.RTD_TEXT) -> {
//                                append("NdefRecord.RTD_TEXT\t")
                                if (record.payload.size > 1) {
                                    append(parseTextRecord(record.payload)).append("\n")
                                }
                            }
                            // 存储统一资源标识符（如 https://example.com）
                            record.type.contentEquals(NdefRecord.RTD_URI) -> {
//                                append("NdefRecord.RTD_URI\t")
                                if (record.payload.size > 1) {
                                    append(parseUriRecord(record.payload)).append("\n")
                                }
                            }
                            // 复合记录，
                            record.type.contentEquals(NdefRecord.RTD_SMART_POSTER) -> {
//                                append("NdefRecord.RTD_SMART_POSTER\t")
                                append(parseSmartPoster(record.payload)).append("\n")
                            }
                            // 其他类型处理...
                        }
                    }
                    // 其他 TNF 类型处理...
                }
            }
        }.trim()
    }

    /**
     * 解析文本记录，从第三个字节开始，后面的文本数据
     */
    private fun parseTextRecord(payload: ByteArray): String {
        //判断文本是基于UTF-8还是UTF-16的，取第一个字节"位与"上16进制的80，16进制的80也就是最高位是1，
        val textEncoding = if (payload[0].toInt() and 0x80 == 0) "UTF-8" else "UTF-16"
        val languageCodeLength = payload[0].toInt() and 0x3F
        val languageCode = String(payload, 1, languageCodeLength, StandardCharsets.US_ASCII)
        return String(
            payload,
            languageCodeLength + 1,
            payload.size - languageCodeLength - 1,
            charset(textEncoding)
        )
    }

    /**
     * 解析NDEF URI数据，从第二个字节开始，后面的文本数据
     */
    private fun parseUriRecord(payload: ByteArray): String {
        val identifierCode = payload[0].toInt() and 0xFF
        val prefix = when (identifierCode) {
            0x00 -> ""
            0x01 -> "http://www."
            0x02 -> "https://www."
            0x03 -> "http://"
            0x04 -> "https://"
            else -> "unknown:"
        }
        return prefix + String(payload, 1, payload.size - 1, StandardCharsets.US_ASCII)
    }

    // 解析Smart Poster记录
    private fun parseSmartPoster(payload: ByteArray) = parseUriRecord(payload)
//    private fun parseAlternativeCarrier(payload: ByteArray) = parseUriRecord(payload)
//    private fun parseHandoverCarrier(payload: ByteArray) = parseUriRecord(payload)
//    private fun parseHandoverRequest(payload: ByteArray) = parseUriRecord(payload)

    // 写入一般文本数据
    fun writeDataToNfcTag(tag: Tag?,data: String ): Boolean {
        val record = NdefRecord.createTextRecord("en", data)
        return writeToNfcTag(tag, record)
    }
    // 拉起app，需要写入包名
    fun writeAppLaunchUriToNfcTag(tag: Tag?, packageName: String): Boolean {
        val record = NdefRecord.createApplicationRecord(packageName)
        return writeToNfcTag(tag, record)
    }
    // 写入 url
//    fun writeUrlToNfcTag(tag: Tag?, url: String): Boolean {
//        val record = NdefRecord.createUri(url.toUri())
//        return writeToNfcTag(tag, record)
//    }
    // 写入经纬度
//    fun writeAddressToNfcTag(tag: Tag?, longitude: String, latitude: String, address: String): Boolean {
//        val uriString = "amapuri://route/plan/?dlat=$latitude&dlon=$longitude&dname=$address"
//        return writeUrlToNfcTag(tag, uriString)
//    }


    private fun writeToNfcTag(tag: Tag?, vararg records: NdefRecord): Boolean {
        if (tag == null) return false

        return try {
            Ndef.get(tag)?.run {
                connect()
                writeNdefMessage(NdefMessage(records))
                close()
                true
            } == true
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }
}